package bb.lanxing.activity.sport;

import static bb.lanxing.activity.sport.SportActivity.EXTRA_LUSHU_ID;
import static bb.lanxing.activity.sport.SportActivity.EXTRA_TITLE;
import static bb.lanxing.activity.sport.SportActivity.EXTRA_TYPE_SPORT;
import static bb.lanxing.model.database.RouteBook.TYPE_BAIDU;

import android.content.ContentValues;
import android.content.Intent;
import android.graphics.Point;
import android.location.Location;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;

import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.TextureMapView;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.PoiInfo;
import com.baidu.mapapi.search.sug.OnGetSuggestionResultListener;
import com.baidu.mapapi.search.sug.SuggestionResult;
import com.baidu.mapapi.search.sug.SuggestionSearch;
import com.baidu.mapapi.search.sug.SuggestionSearchOption;
import com.umeng.analytics.MobclickAgent;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import bb.lanxing.App;
import bb.lanxing.R;
import bb.lanxing.activity.base.BaseActivity;
import bb.lanxing.adapter.POISearchResultAdapter;
import bb.lanxing.common.config.UmengEventConst;
import bb.lanxing.manager.RemoteSharedPreference;
import bb.lanxing.manager.SPConstant;
import bb.lanxing.manager.SystemLocationManagerNew;
import bb.lanxing.model.database.RouteBook;
import bb.lanxing.model.json.BiciLatlng;
import bb.lanxing.network.BaiduHttpClient;
import bb.lanxing.util.BiCiCoorConverter;
import bb.lanxing.util.RouteBookUtil;
import bb.lanxing.util.MapUtil;
import bb.lanxing.util.RxPermissionUtil;
import bb.lanxing.util.map.MapConfigs;
import bb.lanxing.view.BiciAlertDialogBuilder;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

public class SportBeforeActivity extends BaseActivity implements View.OnClickListener {
    public static final String EXTRA_SHOW_ROUTE_PLAN = "isShowRoutePlanButton";

    // 地图控件
    private TextureMapView mMapView;
    private BaiduMap mBaiduMap;
    // 当前定位回到地图中心按钮
    private ImageView location_btn;
    // 导航相关布局
    private FrameLayout naviLayout;
    private EditText searchEditText;
    private TextView search_close;
    private ListView poiResultList;
    private POISearchResultAdapter pOISearchResultAdapter;
    private CardView naviInfoLayout;
    private FrameLayout quick_navi_btn;
    private ImageButton map_cancel_nav;
    // 开启路线规划按钮
    private ImageView routePlanButton;
    // 开始运动按钮
    private TextView sportStartButton;
    private ImageView sport_setting;

    private String title;
    private int sportType;

    private boolean isCheckLocationPermission = false;
    private Location mLocation;
    private LatLng mCurrentLatLng;

    private LatLng mEndLatLng;

    private SuggestionSearch mSuggestionSearch = SuggestionSearch.newInstance();

    private long lushuId;

    private boolean isFirst = true;
    private boolean isManInput = true;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sport_before);

        ImageView back = findViewById(R.id.back);
        back.setOnClickListener(v -> onBackPressed());

        TextView titleView = findViewById(R.id.title);
        Intent intent = getIntent();
        title = intent.getStringExtra(EXTRA_TITLE);
        sportType = intent.getIntExtra(EXTRA_TYPE_SPORT, 0);
        lushuId = intent.getLongExtra(EXTRA_LUSHU_ID, 0);
        titleView.setText(title);

        mMapView = findViewById(R.id.textureMapView);
        mMapView.removeViewAt(1);
        mBaiduMap = mMapView.getMap();
        // 开启定位图层
        mBaiduMap.setMyLocationEnabled(true);

        location_btn = findViewById(R.id.location_btn);
        location_btn.setOnClickListener(this);
        naviLayout = findViewById(R.id.naviLayout);
        searchEditText = findViewById(R.id.searchEditText);
        searchEditText.addTextChangedListener(mTextWatcher);
        search_close = findViewById(R.id.search_close);
        search_close.setOnClickListener(this);
        poiResultList = findViewById(R.id.poi_result_list);
        pOISearchResultAdapter = new POISearchResultAdapter(this);
        poiResultList.setAdapter(pOISearchResultAdapter);
        poiResultList.setOnItemClickListener((parent, view, position, id) -> {
            navToPoi((PoiInfo) pOISearchResultAdapter.getItem(position));
            isManInput = false;
            searchEditText.setText(((PoiInfo) pOISearchResultAdapter.getItem(position)).name);
        });
        naviInfoLayout = findViewById(R.id.navi_info_layout);
        quick_navi_btn = findViewById(R.id.quick_navi_btn);
        quick_navi_btn.setOnClickListener(this);
        map_cancel_nav = findViewById(R.id.map_cancel_nav);
        map_cancel_nav.setOnClickListener(this);

        routePlanButton = findViewById(R.id.routePlanButton);
        routePlanButton.setOnClickListener(this);
        boolean isShowRoutePlanButton = intent.getBooleanExtra(EXTRA_SHOW_ROUTE_PLAN, true);
        if (!isShowRoutePlanButton) {
            routePlanButton.setVisibility(View.GONE);
        }
        sportStartButton = findViewById(R.id.sportStartButton);
        sportStartButton.setOnClickListener(this);
        sport_setting = findViewById(R.id.sport_setting);
        sport_setting.setOnClickListener(this);

        checkLocationPermission();

        mSuggestionSearch.setOnGetSuggestionResultListener(mOnGetSuggestionResultListener);

        RemoteSharedPreference.getInstance().setValue(SPConstant.KEY_SPORT_TYPE, sportType);
        if (lushuId > 0) {
            RouteBook routeBook = RouteBook.getById(lushuId);
            if (null != routeBook) {
                MapUtil.drawSportLushu(mBaiduMap, routeBook, true);
            }
        }
    }

    @Override
    public void onResume() {
        SystemLocationManagerNew.getInstance().registerGpsChangedListener(mGpsChangedListener);
        super.onResume();
    }

    @Override
    public void onPause() {
        SystemLocationManagerNew.getInstance().unregisterGpsChangedListener(mGpsChangedListener);
        super.onPause();
    }

    private void checkLocationPermission() {
        if (RxPermissionUtil.getInstance().checkPermission(this, RxPermissionUtil.getSportPermissions())) {
            runOnUiThread(() -> {
                if (!App.isManagersInit) {
                    App.getContext().initManagersWithPermissions();
                }
                isCheckLocationPermission = true;
                SystemLocationManagerNew.getInstance().registerGpsChangedListener(mGpsChangedListener);
            });
        } else {
            showLocationPermissionDialog();
        }
    }

    private void showLocationPermissionDialog() {
        StringBuilder permissionMessage = new StringBuilder(getResources().getString(R.string.permission_sport_need_loacation) + ":\n");
        List<String> notHadPermissions = RxPermissionUtil.getInstance().getNotHadPermissions(this, RxPermissionUtil.getSportPermissions());
        for (String str : notHadPermissions) {
            permissionMessage.append(str).append("\n");
        }
        new BiciAlertDialogBuilder(this).setTitle(getString(R.string.permission_request_permission_tips)).setMessage(permissionMessage.toString()).setCancelable(true).setPositiveButton(R.string.dialog_btn_ok, (dialogInterface, i) -> requestLocationPermission()).setNegativeButton(R.string.skip, (dialogInterface, i) -> {
        }).show();
    }

    public void requestLocationPermission() {
        RxPermissionUtil.getInstance().setPermissions(RxPermissionUtil.getSportPermissions()).permissionRequestEachCombined(this, new RxPermissionUtil.PermissionCallBack() {
            @Override
            public void granted() {
                runOnUiThread(() -> {
                    if (!App.isManagersInit) {
                        App.getContext().initManagersWithPermissions();
                    }
                    SystemLocationManagerNew.getInstance().registerGpsChangedListener(mGpsChangedListener);
                    isCheckLocationPermission = true;
                });
            }

            @Override
            public void deny() {
                App.getContext().showMessage(R.string.sport_gps_permission_title);
            }
        });
    }

    @Override
    public void onClick(View v) {
        if (!isCheckLocationPermission) {
            checkLocationPermission();
            return;
        }
        if (v.getId() == R.id.location_btn) {
            moveToCenter();
        } else if (v.getId() == R.id.search_close) {
            searchEditText.setText("");
        } else if (v.getId() == R.id.quick_navi_btn) {
            searchWalkingRoute();
        } else if (v.getId() == R.id.map_cancel_nav) {
            toast(R.string.map_cancel_nav_plan);
            naviLayout.setVisibility(View.GONE);
        } else if (v.getId() == R.id.routePlanButton) {
            naviLayout.setVisibility(View.VISIBLE);
            // 清除之前的覆盖物
            mBaiduMap.clear();
            mEndLatLng = null;
        } else if (v.getId() == R.id.sportStartButton) {
            if (mLocation != null) {
                Intent intent = new Intent(this, SportActivity.class);
                intent.putExtra(EXTRA_TITLE, title);
                intent.putExtra(EXTRA_TYPE_SPORT, sportType);
                if (lushuId > 0) {
                    intent.putExtra(EXTRA_LUSHU_ID, lushuId);
                }
                startActivity(intent);
            } else {
                toast(getString(R.string.sport_gps_tip));
            }
        } else if (v.getId() == R.id.sport_setting) {
            MobclickAgent.onEventValue(App.getContext(), UmengEventConst.V30_SPORT_SETTING, null, 1);
            Intent intent = new Intent(this, SportSettingActivity.class);
            intent.putExtra("sportType", sportType);
            startActivity(intent);
        }
    }

    /**
     * 发起路线规划搜索示例
     */
    private void searchWalkingRoute() {
        if (mLocation == null) {
            return;
        }
        // 终点参数
        mEndLatLng = getCenter();
        // 设置起终点信息 起点参数
        ArrayList<BiciLatlng> latlngs = new ArrayList<>();
        latlngs.add(new BiciLatlng(BiCiCoorConverter.baidu2Earth(mCurrentLatLng)));
        latlngs.add(new BiciLatlng(BiCiCoorConverter.baidu2Earth(mEndLatLng)));
        requestBaiduRoadBook(latlngs);
        showLoadingDialog(R.string.map_loading_track, dialog -> toast(R.string.map_toast_cancel_nav_route));
        naviLayout.setVisibility(View.GONE);
    }

    public void requestBaiduRoadBook(final List<BiciLatlng> latlngs) {
        Callback callback = new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                dismissLoadingDialog();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                dismissLoadingDialog();
                if (response.code() == 200) {
                    try {
                        String string = response.body().string();
                        JSONObject jsonObject = new JSONObject(string);
                        RouteBook byId = RouteBook.getById(RouteBookUtil.parseDirection(jsonObject.getJSONObject("result").toString(), latlngs, null, TYPE_BAIDU));
                        if (byId != null) {
                            byId.setTitle(App.getContext().getString(R.string.lushu_title_default));
                            byId.setDisplay(true);
                            byId.setUploadEnable(false);
                            ContentValues contentValues = new ContentValues();
                            contentValues.put("title", byId.getTitle());
                            contentValues.put("isDisplay", byId.isDisplay());
                            contentValues.put("uploadEnable", byId.isUploadEnable());
                            if (App.getContext().isUserSignin()) {
                                byId.setUserAvatar(App.getContext().getSigninUser().getPhotoUrl());
                                contentValues.put("userAvatar", byId.getUserAvatar());
                            }
                            byId.update(contentValues);
                            lushuId = byId.getId();
                            MapUtil.drawSportLushu(mBaiduMap, byId, true);
                            // 形成新路径规划后，顺便把之前的都删了
                            RouteBookUtil.deleteRouteBookBefore(lushuId);
                        }
                    } catch (JSONException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        BaiduHttpClient.buildDirection(latlngs, callback);
    }

    private LatLng getCenter() {
        if (mMapView == null || mBaiduMap == null || mBaiduMap.getProjection() == null) {
            return MapConfigs.getNotNullLastLocation();
        }
        return mBaiduMap.getProjection().fromScreenLocation(new Point(mMapView.getWidth() / 2, mMapView.getHeight() / 2));
    }

    private final SystemLocationManagerNew.GpsChangedListener mGpsChangedListener = new SystemLocationManagerNew.GpsChangedListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            // MapView 销毁后不在处理新接收的位置
            if (mMapView == null) {
                return;
            }
            mLocation = location;
            if (isFirst) {
                moveToCenter();
                isFirst = false;
            }
        }
    };

    private void moveToCenter() {
        if (mLocation == null) {
            return;
        }
        LatLng latLngSystem = new LatLng(mLocation.getLatitude(), mLocation.getLongitude());
        mCurrentLatLng = BiCiCoorConverter.earth2Baidu(latLngSystem);

        MyLocationData locData = new MyLocationData.Builder().accuracy(mLocation.getAccuracy())// 设置定位数据的精度信息，单位：米
                .latitude(mCurrentLatLng.latitude).longitude(mCurrentLatLng.longitude).build();

        mBaiduMap.setMyLocationData(locData);// 设置定位数据, 只有先允许定位图层后设置数据才会生效
        LatLng latLng = new LatLng(mCurrentLatLng.latitude, mCurrentLatLng.longitude);
        MapStatus.Builder builder = new MapStatus.Builder();
        builder.target(latLng).zoom(17.0f);
        mBaiduMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
    }

    private final TextWatcher mTextWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence cs, int start, int before, int count) {
            if (cs.length() <= 0) {
                return;
            }
            // 使用建议搜索服务获取建议列表，结果在onSuggestionResult()中更新
            if (isManInput) {
                mSuggestionSearch.requestSuggestion((new SuggestionSearchOption()).keyword(cs.toString()).city("北京"));
            } else {
                isManInput = true;
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    };

    private final OnGetSuggestionResultListener mOnGetSuggestionResultListener = new OnGetSuggestionResultListener() {
        @Override
        public void onGetSuggestionResult(SuggestionResult suggestionResult) {
            if (suggestionResult == null || suggestionResult.getAllSuggestions() == null) {
                return;
            }
            List<PoiInfo> list = new ArrayList<>();
            for (SuggestionResult.SuggestionInfo info : suggestionResult.getAllSuggestions()) {
                PoiInfo item = new PoiInfo();
                item.setName(info.getKey());
                item.setCity(info.getCity());
                item.setLocation(info.getPt());
                list.add(item);
            }
            pOISearchResultAdapter.updateData(list);
            poiResultList.setVisibility(View.VISIBLE);
            naviInfoLayout.setVisibility(View.GONE);
        }
    };

    private void navToPoi(PoiInfo poiInfo) {
        poiResultList.setVisibility(View.GONE);
        naviInfoLayout.setVisibility(View.VISIBLE);
        mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newLatLng(poiInfo.location));
    }
}